#include "datahandler.h"
#include <QDebug>
#include <QString>
#include <QStringList>
#include <QByteArray>
#include <QFile>
#include <QDateTime>
#include <QDate>
#include <QMessageBox>
#include <QCoreApplication>
/**
 * @brief DataHandler 构造函数
 * 初始化 DataHandler 对象。
 * @param parent 父对象指针
 */
DataHandler::DataHandler(QObject *parent) : QObject(parent)
{
    connect(this, &DataHandler::dataProcessedToStruct, this, &DataHandler::dataReceivedToStructFun);
}


/**
 * @brief 计算数据包的校验位
 * 对给定的数据进行校验计算，返回校验值。
 * @param data 数据包的内容（不包括最后一个字节的校验位）
 * @return 计算出的校验位
 */
quint8 DataHandler::calculateChecksum(const QByteArray &data) const
{
    quint8 checksum = 0;
    for (int i = 0; i < data.size(); ++i) {
        checksum ^= static_cast<quint8>(data[i]);
    }
    return checksum;
}
/**
 * @brief 解算滤光片类型
 * @param filterTypes
 * @return
 */
QString  DataHandler::parseFilterTypes(const QString& filterTypes) {
    QString finalData;

    // 将输入的字符串按逗号分隔
    QStringList hexValues = filterTypes.split(",", Qt::SkipEmptyParts);

    // 去除任何可能的空部分
    hexValues.removeAll("");

    // 临时存储波段名称的字节数组
    QByteArray byteArray;

    for (int i = 0; i < hexValues.size(); ++i) {
        bool ok;
        int hexValue = hexValues[i].trimmed().toInt(&ok, 16);  // 转换为十进制
        if (ok) {
            byteArray.append(static_cast<char>(hexValue));  // 将十进制值转换为字符并添加到 byteArray
        }
    }

    // 将转换后的字节数组转换为 ASCII 字符串
    finalData = QString::fromUtf8(byteArray);

    // 将处理后的字符串按波段名称拆分（使用逗号作为分隔符）
    QStringList wavebands = finalData.split(",", Qt::SkipEmptyParts);

    // 拼接波段名称，确保格式正确
    finalData.clear();
    for (int i = 0; i < wavebands.size(); ++i) {
        finalData += wavebands[i];

        // 如果不是最后一个波段名称，则添加逗号
        if (i + 1 < wavebands.size()) {
            finalData += ",";
        }
    }

    return finalData;
}
/**
 * @brief 校验位校验完成后第一步解算到结构体中
 * @param data
 */
void DataHandler::dataReceivedToStructFun(const QByteArray &data){


    // 提取反馈类型，从第2字节获取
    protocolData.feedbackType = static_cast<quint8>(data[2]);

    // 提取命令，从第3字节获取
    protocolData.command = static_cast<quint8>(data[3]);

    // 提取数据长度，从第4字节获取
    protocolData.dataLength = static_cast<quint8>(data[4]);

    // 确定实际数据长度
    int actualDataLength = (protocolData.dataLength == 0xFF) ?  // 如果数据长度字段为0xFF
                                                                ((static_cast<quint8>(data[5]) << 8) | static_cast<quint8>(data[6])) :  // 使用数据中的前两个字节表示数据长度
                                                                protocolData.dataLength;  // 否则，使用数据长度字段值


    // 提取数据和ACK，数据从第5字节开始，长度为实际数据长度,第5个字节为编号
    protocolData.dataId.clear();
    protocolData.dataId.push_back(data[5]);

    protocolData.data = data.mid(5, actualDataLength);

    //针对观测数据
    if(actualDataLength == 37){
        protocolData.dataVec.clear();
        QByteArray tmpData = protocolData.data.mid(1, protocolData.data.length());


        float  outFvar[9] = {0};
        memcpy(&outFvar, tmpData.data(), tmpData.length());
        for(int i = 0; i < static_cast<int>(tmpData.size()/sizeof(float)); ++i){
            protocolData.dataVec.push_back(outFvar[i]);
        }
    }


    if (5 + actualDataLength - 1 < data.size()) {
        protocolData.ack = static_cast<quint8>(data[5 + actualDataLength - 1]);
    } else {
        qWarning() << "[DataHandler] 提取ACK时超出索引范围!";
    }
    if (6 + actualDataLength - 1 < data.size()) {
        protocolData.checksum = static_cast<quint8>(data[6 + actualDataLength - 1]);  // 提取校验字
    } else {
        qWarning() << "[DataHandler] 提取校验位时超出索引范围!";
    }


    // 判断ACK状态
    QString ackStatus;
    if (protocolData.ack == 0x00) {
        ackStatus = "成功";  // ACK = 0x00表示成功
    } else if (protocolData.ack == 0xFF) {
        ackStatus = "失败";  // ACK = 0xFF表示失败
    } else {
        ackStatus = "未知ACK";  // 处理未知ACK状态
    }

    response.clear();
    switch (protocolData.command) {
    case 0x09: {  // 握手信号
        response.handshakeSignal = QString("握手信号: %1 \n原始帧:%2")
                                       .arg(QString(protocolData.data.toHex(' ').toUpper()))
                                       .arg(QString(data.toHex(' ').toUpper()));  // 将数据转换为十六进制字符串
        break;
    }
    case 0x0F: {  // 设备版本号
        if (protocolData.data.size() >= 3) {  // 确保数据长度足够
            response.deviceVersion = QString("设备版本号: V%1.%2.%3\n原始帧:%4")
                    .arg(static_cast<int>(protocolData.data[0]), 2, 10, QLatin1Char('0'))  // 第一个字节为版本号
                    .arg(static_cast<int>(protocolData.data[1]), 2, 10, QLatin1Char('0'))  // 第二个字节为功能更新
                    .arg(static_cast<int>(protocolData.data[2]), 2, 10, QLatin1Char('0'))
                    .arg(QString(data.toHex(' ').toUpper()));  // 第三个字节为Bug修复
        } else {
            response.deviceVersion = "设备版本号数据不足";  // 数据不足时的提示
        }
        break;
    }
    case 0x10: {  // 设备滤光片类型
        if (protocolData.data.size() >= 55) {  // 确保数据长度足够
            QStringList filterTypes;  // 存储滤光片类型的列表
            for (int i = 0; i < protocolData.data.size(); ++i) {  // 遍历每个字节
                filterTypes.append(QString::number(static_cast<int>(protocolData.data[i]), 16));  // 将字节转换为十六进制字符串
            }
            response.filterTypes = filterTypes.join(", ");  // 将滤光片类型用逗号连接
        } else {
            response.filterTypes = "滤光片数据不足";  // 数据不足时的提示
        }
        break;
    }
    case 0x14: {  // 启动自动测量数据命令响应
        response.autoMeasureResponse = QString("开始采集id: %1\n原始帧:%2")
                                           .arg(QString(protocolData.data.toHex(' ').toUpper()))
                                           .arg(QString(data.toHex(' ').toUpper()));  // 转换为十六进制字符串
        break;
    }
    case 0x15: {  // 读取自动测量数据命令响应
        if (protocolData.data.size() >= 36) {  // 确保数据长度足够
            QStringList strList;
            for (int i = 0; i < protocolData.dataVec.size(); ++i) {
                strList<<QString::number(protocolData.dataVec[i]);
            }
            response.readMeasureResponse = QString("光学厚度: id:%1 float:%2 \n原始帧:%3")
                                            .arg(QString(protocolData.dataId.toHex(' ').toUpper()))
                                            .arg(strList.join(','))
                                            .arg(QString(protocolData.data.toHex(' ').toUpper()));
            //response.readMeasureResponse = QString("自动测量数据命令响应: %1").arg(QString(protocolData.data.toHex(' ').toUpper()));  // 转换为十六进制字符串
            saveRawDataByDay(data);


        } else {
            response.readMeasureResponse = "自动测量数据不足";  // 数据不足时的提示
        }
        break;
    }
    default: {  // 处理未知命令
        response.unknownCommand = QString("未知命令: %1 数据: %2")
                .arg(static_cast<int>(protocolData.command), 2, 16, QLatin1Char('0'))  // 转换命令为十六进制字符串
                .arg(QString(protocolData.data.toHex(' ').toUpper()));  // 转换数据为十六进制字符串
        break;
    }
    }
    emit structDateHandle(response);

}

void DataHandler::saveRawDataByDay(const QByteArray data)
{
    QString dateStr = QDate::currentDate().toString("/rawData/yyyy-MM-dd-RawData.txt");
    QString sLogPath(QCoreApplication::applicationDirPath() + dateStr);
    qDebug()<<sLogPath;

    //将所有原始数据输出到文件中，只输出时间和原始信号，方便绘图
    QFile file(sLogPath);
    if(!file.open(QIODevice::ReadWrite|QIODevice::Append | QIODevice::Text)){
        QMessageBox::critical(nullptr, "错误", "无法打开原始数据" + sLogPath);
    }
    QTextStream stream(&file);

    QDateTime currentTime = QDateTime::currentDateTime().addSecs(-60);
    stream<<currentTime.toString("yyyy:MM:dd HH:mm:ss-")<<data.toHex(' ').toUpper()<<"\r\n";
    file.close();

}
